/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gui;

import fvm.FVElement;
import fvm.FVModelData;
import gui.shapes.JShape;
import gui.shapes.Shape_FVE;
import gui.shapes.Shape_FV_Aqui;
import gui.shapes.Shape_Vec;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Arc2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
import javax.swing.JPanel;
import listener.CanvasEventListener;

/**
 *
 * @author BIM1LA
 */
public class JCanvas extends JPanel implements MouseListener, MouseMotionListener {

    private int timestep = 0, timesteps = 0;
    final int offset = 0;
    ArrayList<JShape> shapes = new ArrayList<JShape>();
    ArrayList<Shape_FV_Aqui> aquish;
    HashMap<Shape_FVE, FVElement> hashmap;
    Dimension dim;
    FVModelData fvmd;
    public boolean showstützstellen = false;
    public boolean showfvframes = false;
    public boolean showfvcolors = true;
    public boolean showaquilines = false;
    ArrayList<Shape_FVE> selectedshpes;
    JColorBar colorbar;
    CanvasEventListener canvas_event;
    MouseEvent mousepressed = null;
    MouseEvent mousedragged = null;
    MouseEvent mousereleased = null;
    boolean bplotq = false;
    public boolean calculatedaqui= false;
    public int aplotq = 1;
    public double splotq = .15;
    
    public JCanvas() {

        selectedshpes = new ArrayList<>();
        //setDoubleBuffered(true);
        setBackground(Color.white);
        dim = new Dimension(this.getSize());
        this.addMouseListener(this);
        this.addMouseMotionListener(this);

        hashmap = new HashMap<>();
        // Shape_FVE shape1 = new Shape_FVE(dim, offset, .5, .5, .5, .5);

        //shapes.add(shape1);

    }

    public void addCanvasEventListener(CanvasEventListener cel) {

        this.canvas_event = cel;
    }

    public void addColorBar(JColorBar colorbar) {
        this.colorbar = colorbar;
    }

    public void addshape(JShape s) {

        shapes.add(s);

    }

    public void deleteshape(JShape s) {

        shapes.remove(s);

    }

    public void setModel(FVModelData fvmd) {
        this.fvmd = fvmd;
        createModel();
    }
    
    public void setplotqb(boolean bool){bplotq = bool;}
    public boolean getplotqb(){return bplotq;}

    public void createModel() {
        selectedshpes = new ArrayList<>();
        shapes = new ArrayList<>();
        showfvframes = true;
        for (int i = 0; i < fvmd.getElements().size(); i++) {
            for (int j = 0; j < fvmd.getElements().get(0).size(); j++) {



                double x, y, dx, dy;

                x = fvmd.getElements().get(i).get(j).getsupppoint().x / fvmd.sizex;
                y = fvmd.getElements().get(i).get(j).getsupppoint().y / fvmd.sizey;
                dx = fvmd.dx / fvmd.sizex / 2;
                dy = fvmd.dy / fvmd.sizey / 2;

                Shape_FVE s = new Shape_FVE(dim, 0., x, 1 - y, dx, dy);
                //Random rand = new Random();
                //s.setColor(new Color((float)((rand.nextGaussian()+0.5)*0.14), (float) ((rand.nextGaussian()+0.5)*0.14), (float) ((rand.nextGaussian()+0.5)*0.14) ));
                //s.setColor(new Color((float) Math.random(), (float) Math.random(), (float) Math.random()));
                if (fvmd.getElements().get(i).get(j).isboundary()) {
                    s.setColor(Color.GRAY);
                }
                if (fvmd.getElements().get(i).get(j).isnoflow()) {
                    s.setColor(Color.BLACK);
                }

                // else s.setColor(Color.WHITE);
                //s.setColor(Color.yellow);
                shapes.add(s);
                hashmap.put(s, fvmd.getElements().get(i).get(j));
                fvmd.getElements().get(i).get(j).addshape(s);

            }
        }

    }

    protected void paintComponent(Graphics g) {

        dim.setSize(this.getSize());

        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);


        super.paintComponent(g2);


        if ((!showfvframes) && (!showfvcolors)) {
        
            
             for (int i = 0; i < shapes.size(); i++) {
                

                Shape_FVE sha = (Shape_FVE) shapes.get(i);
                
                                if(!showfvcolors&&hashmap.get(sha).isnoflow()){
                g2.setColor(Color.GRAY.darker().darker());
                g2.fill(sha);
                g2.draw(sha);
                
                }
                               
                if(!showfvcolors&&hashmap.get(sha).isboundary()&&!hashmap.get(sha).isnoflow()){
                g2.setColor(Color.GRAY);
                g2.fill(sha);
                g2.draw(sha);
                }
                
             }
        
        }
        if ((showfvframes) || (showfvcolors)) {

            g.setColor(Color.blue);

            for (int i = 0; i < shapes.size(); i++) {
                // g2.setColor(new Color((float) Math.random(), (float) Math.random(), (float) Math.random()));

                Shape_FVE sha = (Shape_FVE) shapes.get(i);
              
               
                if(!showfvcolors&&hashmap.get(sha).isnoflow()){
                g2.setColor(Color.GRAY.darker().darker());
                g2.fill(sha);
                }
                               
                if(!showfvcolors&&hashmap.get(sha).isboundary()&&!hashmap.get(sha).isnoflow()){
                g2.setColor(Color.GRAY);
                g2.fill(sha);
                }
                if (showfvcolors) {

                    


                    // g2.setColor(shapes.get(i).getColor());

                    if (hashmap.get(sha).isboundary()||hashmap.get(sha).isnoflow()) {

                        g2.setColor(Color.GRAY);

                        if (hashmap.get(sha).isnoflow()) {

                            g2.setColor(Color.GRAY.darker().darker());

                        }

                    } else {


                        //g2.setColor(colorbar.getColor(hashmap.get(sha).geth(timestep)));
                        g2.setColor(colorbar.getColor(hashmap.get(sha).gethk()));
                        if(colorbar.getColor(hashmap.get(sha).gethk()) == null){g2.setColor(Color.MAGENTA.darker());}
                    }
                    //if(colorbar.getColor(hashmap.get(sha).gethk()) == null){g2.setColor(Color.MAGENTA);}
                    //System.out.println(colorbar.getColor(hashmap.get(sha).gethk()));
                    g2.fill(shapes.get(i));

                }
                
                                    if (!showfvframes && showfvcolors) {g2.draw(shapes.get(i));}
                    else{
                                        if(showfvframes){
                        g2.setColor(Color.BLACK);
                        g2.draw(shapes.get(i));
                    }}
                
//                if (showfvframes) {
//                    g2.setColor(Color.BLACK);
//                } else {
//                   
//                    g2.setColor(colorbar.getColor(hashmap.get(sha).geth(timestep)));
//                }
//                g2.draw(shapes.get(i));

            }
        }
        if (!showfvcolors) {
            g2.setColor(Color.BLUE);
            for (int j = 0; j < selectedshpes.size(); j++) {
                g2.fill(selectedshpes.get(j));
            }
        }
        g.setColor(Color.black);

        if (fvmd != null && showstützstellen) {

            for (int i = 0; i < fvmd.getElements().size(); i++) {
                for (int j = 0; j < fvmd.getElements().get(0).size(); j++) {

                    Shape arc = //       x,   y,  w,  h, start, extend, type 
                            new Arc2D.Double(fvmd.getElements().get(i).get(j).getsupppoint().x / fvmd.sizex * (dim.width) - 2,
                            fvmd.getElements().get(i).get(j).getsupppoint().y / fvmd.sizey * (dim.height) - 2, 4, 4, 0, 360, Arc2D.OPEN);
                    g2.draw(arc);
                    g2.fill(arc);


                }
            }


        }



        g2.setStroke(new BasicStroke(2));

        g2.drawLine(offset, offset, offset, this.getHeight() - offset);
        g2.drawLine(offset, offset, this.getWidth() - offset, offset);
        g2.drawLine(offset, this.getHeight() - offset - 1, this.getWidth() - offset, this.getHeight() - offset - 1);
        g2.drawLine(this.getWidth() - offset - 1, offset, this.getWidth() - offset - 1, this.getHeight() - offset);

        g2.setStroke(new BasicStroke(1));

if(bplotq){
        for (int i = 0; i < shapes.size(); i++) {

            if(!hashmap.get(shapes.get(i)).isboundary()&&!hashmap.get(shapes.get(i)).getSouthNeigh().isboundary()
                    &&!hashmap.get(shapes.get(i)).getWestNeigh().isboundary()&&!hashmap.get(shapes.get(i)).getEastNeigh().isboundary()
                    &&!hashmap.get(shapes.get(i)).getNorthNeigh().isboundary()){
            
                 Shape_FVE fvs = (Shape_FVE) shapes.get(i);
            FVElement fve = hashmap.get(fvs);
                if(fve.geti()%aplotq == 0 && fve.getj()%aplotq == 0){
                    
            Shape_Vec s = new Shape_Vec(dim, fvs.getx_rel(), fvs.gety_rel(), fve.getqx(1), fve.getqy(1), fvs);
            s.setscale1(splotq);
            s.setscale2(270);
            
            g2.draw(s);
            g2.fill(s);
                    
                }
                
//            if(shapes.size()>3500){
//                
//                if(shapes.size()>10000){
//                
//                 Shape_FVE fvs = (Shape_FVE) shapes.get(i);
//            FVElement fve = hashmap.get(fvs);
//                if(fve.geti()%5 == 0 && fve.getj()%5 == 0){
//                       
//
////            if(fve.getqx(timestep)!=0){
////                System.out.println("nsujd");
////            }
//
//                    
//            Shape_Vec s = new Shape_Vec(dim, fvs.getx_rel(), fvs.gety_rel(), fve.getqx(1), fve.getqy(1), fvs);
//            s.setscale1(10);
//            s.setscale2(270);
//            
//            g2.draw(s);
//            g2.fill(s);
//                
//                
//            }
//                
//                }
//                else{
//            
//                 Shape_FVE fvs = (Shape_FVE) shapes.get(i);
//            FVElement fve = hashmap.get(fvs);
//                if(fve.geti()%3 == 0 && fve.getj()%3 == 0){
//                       
//
////            if(fve.getqx(timestep)!=0){
////                System.out.println("nsujd");
////            }
//
//            Shape_Vec s = new Shape_Vec(dim, fvs.getx_rel(), fvs.gety_rel(), fve.getqx(1), fve.getqy(1), fvs);
//            s.setscale1(.15);
//            s.setscale2(300);
//            
//            g2.draw(s);
//            g2.fill(s);
//                
//                
//            }}}
//            else{
//            Shape_FVE fvs = (Shape_FVE) shapes.get(i);
//            FVElement fve = hashmap.get(fvs);
//
////            if(fve.getqx(timestep)!=0){
////                System.out.println("nsujd");
////            }
//
//            Shape s = new Shape_Vec(dim, fvs.getx_rel(), fvs.gety_rel(), fve.getqx(1), fve.getqy(1), fvs);
//            g2.draw(s);
//            g2.fill(s);
//        }
            }
        }
}

if(showaquilines && calculatedaqui){
    
 for(int i=0; i < aquish.size(); i++){
     
     if(showfvcolors){g2.setColor(Color.black);
     }
     else{
    
         g2.setColor(colorbar.getColor(aquish.get(i).getaquih()));
         
     }
     
     g2.draw(aquish.get(i));
 
 }
        
        
}

        //  System.out.println("");
    }
    
    
    public void calculateAquilines(){
    
       double min = colorbar.getlowerb();
    double max = colorbar.getupperb();
    
    int al = 50;
    double[] alsteps = new double[al+1];
    
    for(int i = 0; i <= al; i++){
    
        alsteps[i] = min+ ((max-min)/al*i);
    
    }
    
    
    
    aquish = new ArrayList<>();
        for (int i = 0; i < shapes.size(); i++) {


            Shape_FVE fvs = (Shape_FVE) shapes.get(i);
            FVElement fve = hashmap.get(fvs);
if(!fve.isboundary()&&!fve.getNorthNeigh().isboundary()&&!fve.getSouthNeigh().isboundary()
        &&!fve.getWestNeigh().isboundary()&&!fve.getEastNeigh().isboundary()){
            double nw = fve.gethNW();
            double ne = fve.gethNE();
            double sw = fve.gethSW();
            double se = fve.gethSE();
            
          
            
            int mi = 0, ma = 0;
            
            if(nw>=min&&ne>=min&&se>=min&&sw>=min){
            
//            if(nw < min){nw = min;}
//            if(ne < min){ne = min;}
//            if(sw < min){sw = min;}
//            if(se < min){se = min;}
                
          
                
            for(int j = 0; j <= al; j++){
            
                if(alsteps[j] <= nw && alsteps[j] <= ne &&alsteps[j] <= sw &&alsteps[j] <= se){mi = j;}
                if(alsteps[j] >= nw && alsteps[j] >= ne &&alsteps[j] >= sw &&alsteps[j] >= se){ma = j;
                break;}

            }
            
                  
            
                if(ma-mi>0){
                
 
                    ArrayList<Double> aquil = new ArrayList<>();
                    ArrayList<Double> aquip = new ArrayList<>();
                    
                    aquip.add(nw);
                    aquip.add(ne);
                    aquip.add(sw);
                    aquip.add(se);
                    
                    for(int n = 1; n < ma-mi; n++){
                    
                    aquil.add(alsteps[mi+n]);
                    }
                    
                    
                    for(int u = 0; u < aquil.size(); u++){
                    Shape_FV_Aqui ash = new Shape_FV_Aqui(fvs.getdim(),fvs.getoffset(), fvs.getx_rel(), fvs.gety_rel(), fvs.getdx_rel(), fvs.getdy_rel(),u);
                    
                    ash.setaquil(aquil);
                    ash.setaquip(aquip);
                    ash.setbaqui(true);
                    aquish.add(ash);
                    
                    
                    }
                    
                    
                
                }
                
            
            }


        }}
    
    calculatedaqui = true;
    }

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {


        mousedragged = null;
        mousereleased = null;
        mousepressed = e;

//        for (int i = 0; i < selectedshpes.size(); i++) {
//            
//            selectedshpes.get(i).setColor(selectedshpes.get(i).getColor().brighter());
//            
//        }

//        for (int i = 0; i < shapes.size(); i++) {
//            if (shapes.get(i).contains(e.getX(), e.getY())) {
//
//
//                selectedshpes = new ArrayList<>();
//                selectedshpes.add((Shape_FVE)shapes.get(i));
//                selectedshpes.get(0).setColor(selectedshpes.get(0).getColor().darker());
//               // selectedshpes.get(0).setColor(Color.red);
//              
//                FVElement temp = hashmap.get(selectedshpes.get(0));
//                
//                canvas_event.Element_clicked(temp);
//                //System.out.println("clicked");
////                System.out.println("Element: "+temp.geti()+temp.getj()+" x: "+temp.getsupppoint().x+" y: "+temp.getsupppoint().y);
////                System.out.println("h: "+temp.getlasth());
////                System.out.println("n0: "+temp.getlastNe());
////                FVElement tempn = temp.getNorthNeigh();
////                FVElement tempe = temp.getEastNeigh();
////                FVElement temps = temp.getSouthNeigh();
////                FVElement tempw = temp.getWestNeigh();
////                
////                if(tempn!=null) System.out.println("Nord: "+tempn.geti()+tempn.getj());
////                if(tempe!=null) System.out.println("Osten: "+tempe.geti()+tempe.getj());
////                if(temps!=null) System.out.println("Süden: "+temps.geti()+temps.getj());
////                if(tempw!=null) System.out.println("Westen: "+tempw.geti()+tempw.getj());
//                //System.out.println("");
//                
//                
//               
//                repaint();
//                break;
//
//            }
//        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {

        mousereleased = e;
        canvasevent();
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    public void setTimeSteps(int timesteps) {
        this.timesteps = timesteps;
    }

    public void setTimeStep(int timestep) {
        this.timestep = timestep;
    }

    @Override
    public void mouseDragged(MouseEvent e) {

        mousedragged = e;
    }

    @Override
    public void mouseMoved(MouseEvent e) {
    }

    private void canvasevent() {

        boolean click;

        if (mousedragged == null) {
            click = true;
        } else {
            click = false;
        }


        if (click) {

            for (int i = 0; i < shapes.size(); i++) {

                if (shapes.get(i).contains(mousereleased.getX(), mousereleased.getY())) {


                    selectedshpes = new ArrayList<>();
                    selectedshpes.add((Shape_FVE) shapes.get(i));
                    selectedshpes.get(0).setColor(selectedshpes.get(0).getColor().darker());
                    // selectedshpes.get(0).setColor(Color.red);

                    FVElement temp = hashmap.get(selectedshpes.get(0));

                    canvas_event.Element_clicked(temp);
                    repaint();
                    break;

                }
            }


        }
        else{
        
                ArrayList<FVElement> elements = new ArrayList<>();
                selectedshpes = new ArrayList<>();
                Rectangle r;
                int x,y,
                    widht = Math.abs(mousereleased.getX()-mousepressed.getX()),
                    height = Math.abs( mousereleased.getY()-mousepressed.getY());
                if(mousepressed.getX()<mousereleased.getX())
                    x = mousepressed.getX();
                else
                    x = mousereleased.getX();
                
                if(mousepressed.getY()<mousereleased.getY())
                    y = mousepressed.getY();
                else
                    y = mousereleased.getY();
                
                r = new Rectangle(x, y, widht, height);
                
               for (int i = 0; i < shapes.size(); i++) {

                if (shapes.get(i).intersects(r)) {


                    
                    selectedshpes.add((Shape_FVE) shapes.get(i));
                    //selectedshpes.get(0).setColor(selectedshpes.get(0).getColor().darker());
                    // selectedshpes.get(0).setColor(Color.red);

                    FVElement temp = hashmap.get((Shape_FVE)shapes.get(i));
                    elements.add(temp);
                  
                   
                   

                }
            }
        
               mousepressed = null;
               mousereleased = null;
               mousedragged = null;
               canvas_event.Elements_dragged(elements);
               repaint();
        
        }






    }
}
